#
#  Copyright (C) 2012
#  University of Rochester Department of Computer Science
#    and
#  Lehigh University Department of Computer Science and Engineering
#
# License: Modified BSD
#          Please see the file LICENSE.RSTM for licensing information

#
# Pull in the 'info' target, which is the default if a platform isn't
# specified, and the names of the TM algorithms
#
MKFOLDER = ../build
include $(MKFOLDER)/info.mk
include $(MKFOLDER)/algs.mk

#
# Output folder: we build in-tree, unless this is overridden.  Note that the
# folder is built at parse time, so that we don't have to depend on its
# existance, but we need to handle parses of this file when a library wasn't
# given
#
ODIR := obj.$(PLATFORM)
ifeq ($(ODIR),obj.)
else
output_folder := $(shell mkdir -p $(ODIR))
endif

#
# Updates to flags: we want support for dependencies, and we build an .h file
#                   in the ODIR that we need to have on the include path
#
CXXFLAGS += -MMD -I$(ODIR)

#
# Names of the supporting files that we need to build.  The STM names are in
# STMAGLS, from ../build/algs.mk
#
COMMONNAMES = WBMMPolicy Common CommonLazy CommonOrec tx adaptivity

#
# Transform all source names to .o files in the output directory
#
ALGOFILES    = $(patsubst %, $(ODIR)/%.o, $(STMALGS))
COMMONOFILES = $(patsubst %, $(ODIR)/%.o, $(COMMONNAMES))
.PRECIOUS: $(ALGOFILES) $(COMMONOFILES)

#
# The algorithm names indicate the names of the libXYZ.a files to build
#
LIBS = $(patsubst %, $(ODIR)/lib%.a, $(STMALGS))

#
# AdapTM requires an autogenerated header file with all the algorithm names
# and a different set of .o files (but note that AdapTM itself is in STMALGS)
#
ADAPTHEADER = $(ODIR)/tmnames.autobuild.h
ADAPTER = $(ODIR)/tmnames.autobuild.cpp

ADAPTNAMES  = WBMMPolicy Common CommonLazy CommonOrec adaptivity tmnames.autobuild
ADAPTOFILES = $(patsubst %, $(ODIR)/%.o, $(ADAPTNAMES))
ADAPTLIB    = $(ODIR)/libAdapTM.a
.PRECIOUS: $(ADAPTOFILES)

ADAPTIVITYCPP = AdapTM.cpp
#
# Dependencies
#
DEPS = $(patsubst %, $(ODIR)/%.d, $(STMALGS) $(COMMONNAMES) $(ADAPTNAMES))
-include $(DEPS)

$(ADAPTIVITYCPP): $(MKFOLDER)/algs.mk AdapTM_gen.pl 
	rm -fr $@
	perl AdapTM_gen.pl $(STMALGS) > $@
#
# Rule for building individual .o files
#
$(ODIR)/%.o: %.cpp
	@echo [CXX] $< "-->" $@
	@$(CXX) $(CXXFLAGS) -c -o $@ $<

#
# Rule for building per-TM .a files
#
$(ODIR)/lib%.a: $(ODIR)/%.o $(COMMONOFILES)
	@echo [AR] $@
	@$(AR) cru $@ $^

#
# Custom rule for libadaptm.a
#
$(ADAPTLIB): $(ADAPTOFILES) $(ALGOFILES)
	@echo [AR] $@
	@$(AR) cru $@ $^

#
# Build a custom header file with the names of all algorithms in an ENUM
#
$(ADAPTHEADER): $(MKFOLDER)/algs.mk
	@echo "namespace stm {" > $@
	@echo $(STMALGS) TM_NAMES_MAX | sed -e 's/ /, /g' -e 's/^/enum TM_NAMES {/' -e 's/MAX/MAX};/' >> $@
	@echo "extern char* TM_NAMES_STRING[];" >> $@
	@echo "}" >> $@

$(ADAPTER): $(MKFOLDER)/algs.mk
	@echo "#include \"tmnames.autobuild.h\"" > $@
	@echo "namespace stm {" >> $@
	@echo $(STMALGS) TM_NAMES_MAX | sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' -e 's/ /", "/g' -e 's/^/char* TM_NAMES_STRING[] = {"/g' -e 's/max/max"};/' >> $@
	@echo "}" >> $@

#
# Simply typing 'make' dumps a message, rather than trying to guess a default
# platform.  librstm is the correct target, but isn't going to work if the
# directions are not followed
#
.default: info
librstm: $(ADAPTHEADER) $(LIBS)
.PHONY: .default librstm

#
# In order to avoid creating config files, we use the following approach:
# when we make, we give the name of a platform being targeted.  If that
# platform exists, then there's a file in $(MKFOLDER) with the platform as
# its basename and .mk as its suffix.  If we re-invoke make including that
# platform as an additional makefile (to this one), then we'll have all the
# definitions we need to build the right way.
#
%: $(MKFOLDER)/%.mk
	MAKEFILES="$<" $(MAKE) librstm
